home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / win / pascal / modialg.exe / README.TXT < prev   
Encoding:
Text File  |  1991-11-30  |  9.8 KB  |  214 lines

  1.  
  2.               Using Modeless Dialogs as MDI Child Windows
  3.               -------------------------------------------
  4.  
  5. This file contains important information for using the TPW MDITypes
  6. unit.  You should read this before using the unit.  As of this writing
  7. (11/30/91 at 3:43 PM), the code works well.  There were problems with
  8. sporadic UAEs in my previeous testing, but these seem to have been
  9. resolved.  The upshot of the exercise has been to follow these rules:
  10.  
  11. 1.  *NEVER* change the style bits of an MDI child window after it has
  12.     been created.  This makes Windows unstable.
  13.  
  14. 2.  *NEVER* delete menu items from the system menu of the MDI child
  15.     window.  You can disable menu items, but deleting them seems to
  16.     lead to further Windows instability.
  17.  
  18. 3.  If you want to prevent a windoe from changing size, handle
  19.     wm_SysCommand and check for Msg.wParam = sc_Size, sc_Maximize,
  20.     and/or wm_Minimize.  Return 1 in Msg.Result if you see these values,
  21.     otherwise call DefWndProc(Msg).
  22.  
  23. The program now seems steady as a rock.  The MDI child windows
  24. containing dialog boxes don't look exactly like I wanted them to look,
  25. but the program doesn't crater Windows any more.  I'm willing to live
  26. with the aesthetics for now.
  27.  
  28. The archive file contains the following files:
  29.  
  30. MDIEXAM  ACL      237   Test program accelerators
  31. MDIDLG1  DLG     1185   Test program MDI child dialog #1
  32. MDIDLG2  DLG      578   Test program MDI child dialog #2
  33. DIALOG1  ICO     1846   Icon for MDI child dialog #1 windows
  34. DIALOG2  ICO     1846   Icon for MDI child dialog #2 windows
  35. MDIEDIT  ICO     1846   Icon for MDI child edit windoww
  36. MDIEXAM  ICO     1846   Icon for MDI test program
  37. MDIEXAM  INC      735   Include file for the test program
  38. MDIEDIT  MNU      802   Dialog & edit child windows menu
  39. MDIEXAM  MNU      502   Frame menu for case of no children
  40. MDIRECT  MNU      535   Random rectangle child windows menu
  41. MDIEXAM  PAS    44832   Test program source code
  42. MDITYPES PAS    27672   MDI child window unit source code
  43. MDIEXAM  RC       328   Test program RC file.  For use with RW or WRT!
  44.  
  45. The MDITypes unit is the heart of the implementation.  There are three
  46. different object types defined in the unit, as follows:
  47.  
  48. TMDIChild:   TMDIChild descends from TWindow.  The type supports
  49.              changing the current menu displayed by the frame window
  50.              when an MDI child window is activated or deactivated.  To
  51.              accomplish this end, the type defines a response method for
  52.              the wm_MDIActivate message.
  53.  
  54. TMDIDialog:  This type descends from TMDIChild.  It supports the concept
  55.              of a modeless dialog as an MDI child window.
  56.  
  57. TMDIFrame:   This type is a descendant of TMDIWindow.  It defines three
  58.              methods that were not included TMDIWindow.  These allow you
  59.              to find the OWL object associated with an MDI child window
  60.              handle (GetChild(TheWnd:  HWnd)); closing a specific child
  61.              window (TMDIWindow only supports closing all child windows;
  62.              to destroy a single window, you have to double click on the
  63.              child's system menu); and a wm_InitMenu reponse method to
  64.              simplify the process of allowing an MDI child window to
  65.              modify the state of the current menu.  This is useful for
  66.              those cases where you have an Edit menu, for example, and
  67.              you need to gray items on it based on whether or not you
  68.              can undo an edit, paste, cut, etc.
  69.  
  70. The source code is heavily commented, so you should be able to follow
  71. all that is going on in it.  Any questions should be directed to me,
  72. Tony Vitabile 76054, 1450 on BPROGA section 8.
  73.  
  74.  
  75. USING MULTIPLE MENUS IN AN MDI PROGRAM
  76. --------------------------------------
  77.  
  78. Being able to have a different menu be displayed when a particular type
  79. of MDI child window is currently active is a major feature of the MDI
  80. specification.  However, OWL doesn't provide any support for this
  81. feature.  This isn't a difficult feature to support, but it would be
  82. easier if there were an object type that encapsulated all the work
  83. involved for you.  Now there is such an object type:  TMDIChild.  Here's
  84. how you use it.
  85.  
  86. Define an object type in your program that descends from TMDIChild.
  87. This allows you to add other functionality your window may need in
  88. addition to that provided by TMDIChild.  In your Init constructor, you
  89. provide two additional pieces of information that the TMDIChild window
  90. will need to support switching the frame menu.  These are:
  91.  
  92. -       A handle to the menu to be displayed when this window is active;
  93. -       The position number of the Window popup menu item on the menu.
  94.  
  95. TMDIChild stores this information in two fields, then determines the
  96. menu handle of the Window popup menu and saves that as well.  That's all
  97. you have to do.  From here on, changing the menu is automatically
  98. handled by TMDIChild's methods.
  99.  
  100. When a TMDIChild receives a wm_MDIActivate message, the wParam field
  101. tells the window whether it's being activated or deactivated.  TMDIChild
  102. uses this information to determine whether it should switch to the frame
  103. window's default menu (the one included in the frame window's Init
  104. constructor) or the one whose handle is contained in this instance of
  105. TMDIChild.  The wm_MDIActivate response method retrieves the appropriate
  106. handles from the appropriate objects, then sends the wm_MDIChangeMenu
  107. message to the MDI Client window.  After that, the job is done.
  108.  
  109. Note that Load & Store methods are provided for TMDIChild so that you
  110. can save descendants and instances of this type on streams.  See the
  111. section at the end of this README.TXT file for more information
  112. regarding the proper streaming of TMDIChild & its descendants.
  113.  
  114.  
  115.  
  116. USING A MODELESS DIALOG AS AN MDI CHILD WINDOW
  117. ----------------------------------------------
  118.  
  119. So you want to use a modeless dialog box as an MDI child window?  Well,
  120. it's not quite as easy as it might seem, nor is it as difficult as you
  121. may think.  The MDITypes unit was written to provide a basis for
  122. supporting this type of feature in your programs.  All the work involved
  123. in maintaining a window of this type is encapsulated in the type
  124. TMDIDialog.  The paragraphs that follow describe how you extend this
  125. type to include your dialog box.
  126.  
  127. TMDIDialog is an abstract type.  A window of type TMDIDialog itself
  128. should never exist.  This is because TMDIDialog is a generic type and
  129. does not have a predefined dialog template that it uses.  YOUR code
  130. supplies that template.  After you make the dialog known, TMDIDialog's
  131. methods then do all the work.
  132.  
  133. TMDIDialog defines a new method called InitDialog.  This is a function
  134. that returns a pointer to an object of type TDlgWindow.  To create your
  135. own MDI dialog box type, you descend from TMDIDialog and then override
  136. InitDialog.  InitDialog should call New, passing the constructor of
  137. an object descended from type TDlgWindow.  The value returned by New is
  138. the value you return to InitDialog's caller.  For example:
  139.  
  140. type
  141.   MyDialog    = object (TDlgWindow)
  142.                   .
  143.                   .
  144.                   .
  145.                 end;
  146.   MyMDIDialog = object (TMDIDialog)
  147.                   .
  148.                   .
  149.                   .
  150.                   function InitDialog:  PDlgWindow;
  151.                     virtual;
  152.                   .
  153.                   .
  154.                   .
  155.                 end;
  156.                 .
  157.                 .
  158.                 .
  159.   function MyMDIDialog.InitDialog:  PDlgWindow;
  160.     begin       { MyMDIDialog.InitDialog }
  161.       InitDialog := PDlgWindow(New(PMyDialog, Init(...)))
  162.     end         { MyMDIDialog.InitDialog };
  163.  
  164. That's it!  From here on, TMDIDialog takes care of all the details.
  165.  
  166. Of course, if you want your MDI dialog type to do more, you'll have to
  167. add methods to cover those situations.
  168.  
  169. The sample program included in this archive, MDIEXAM.PAS, shows how to
  170. create 2 different types of MDI dialog child windows.
  171.  
  172.  
  173. STREAMING TMDICHILD DESCENDANTS
  174. -------------------------------
  175.  
  176. The Load & Store methods for both TMDIChild & TMDIDialog take pretty
  177. simplistic approaches to reading & writing windows of these types on
  178. streams.  They assume the value written to the stream for a menu handle
  179. will be valid when the window is read.  This is *NOT* true, but there is
  180. nothing that TMDIChild or TMDIDialog can do about about it, since they
  181. have no way of knowing the resource name associated with that menu.
  182.  
  183. If you intend to stream your TMDIChild and/or TMDIDialog descendants,
  184. you should put some code in your descendant's Load/Store method to make
  185. sure that the menu handles in your windows are correct.  For example:
  186.  
  187. constructor MyMDIChild.Load(var S:  TStream);
  188.   begin         { MyMDIChild.Load }
  189.                    { Get the window from the stream }
  190.     TMDIChild.Load(S);
  191.                         { Now fix up the menus }
  192.     Menu := LoadMenu(HInstance, mymenu);        { or use a global var }
  193.     WndMenu := GetSubMenu(Menu, MenuPos)        { Set windo menu properly}
  194.   end           { MyMDIChild.Load };
  195.  
  196. This will properly initialize the menu handles for the MDI child window.
  197. It is important that you set WndMenu too!  Failure to do so will have
  198. unpredictable results, and may crash Windows.
  199.  
  200. If your window is a descendant of MDIDialog, you will need to implement
  201. code like that above.  Make sure you call TMDIDialog.Load instead of
  202. TMDIChild.Load.  TMDIDialog.Load calls TMDIChild.Load and performs
  203. additional steps required for the type.
  204.  
  205.  
  206. COPYRIGHT
  207. ---------
  208.  
  209. The program and unit source code included in this archive are Copyright
  210. (c) 1991 by Anthony M.  Vitabile.  All rights are reserved.  Permission
  211. is hereby granted to all who desire to use this source code in their
  212. programs provided the above copyright is included in the program.
  213.  
  214.